package xdu.lz.stage2_design_pattern.chapter2_single_pattern;

//懒汉加载模式：去获得对象的时候才去试着创建，带来的问题是线程安全
public class Singleton2 {

    private static Singleton2 instance;

    public String obj;
    private Singleton2(){
        //empty
        /*try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
*/        obj = "111";
    }

    //方式1：thread-safe
    public static Singleton2 getInstance1(){
        //这里会线程安全
        if(instance == null){
            instance = new Singleton2();
        }
        return instance;
    }

    //方式2：这样加锁，会导致以后每次get都会加载，效率太低
    public static Singleton2 getInstance2(){
        synchronized (Singleton2.class){
            if(instance == null){
                instance = new Singleton2();
            }
        }
        return instance;
    }
    //方式3：会导致空指针异常，说明见singleton3
    public static Singleton2 getInstance3(){
        if(instance == null){
            //这样加锁只会在创建的时候加锁 ，其他任何时候获取不会进来的，效率很高。
            //注意可能第一次创建的时候会有多个线程判断是null，
            //所以在同步代码快创建instance前还需要判断是否是null来确保实例唯一。
            synchronized (Singleton2.class){
                if(instance == null){
                    instance = new Singleton2();
                }
            }
        }
        return instance;
    }
    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                System.out.println(Singleton2.getInstance1());
//                System.out.println(Singleton2.getInstance3().obj);
            }).start();
        }
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(System.currentTimeMillis() - time);
    }
}
